<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
  <meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />

  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Memory Management &mdash; SIMULATeQCD 0.7 documentation</title>
      <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
      <link rel="stylesheet" href="../_static/css/theme.css" type="text/css" />
      <link rel="stylesheet" href="../_static/togglebutton.css" type="text/css" />
      <link rel="stylesheet" href="../_static/custom.css" type="text/css" />
  <!--[if lt IE 9]>
    <script src="../_static/js/html5shiv.min.js"></script>
  <![endif]-->
  
        <script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
        <script src="../_static/jquery.js"></script>
        <script src="../_static/underscore.js"></script>
        <script src="../_static/doctools.js"></script>
        <script src="../_static/togglebutton.js"></script>
        <script>var togglebuttonSelector = '.toggle, .admonition.dropdown';</script>
    <script src="../_static/js/theme.js"></script>
    <link rel="index" title="Index" href="../genindex.html" />
    <link rel="search" title="Search" href="../search.html" />
    <link rel="next" title="Multi-GPU: Distribution of local lattices on the individual GPUs" href="multiGPU.html" />
    <link rel="prev" title="How to make an input parameter file" href="inputParameter.html" /> 
</head>

<body class="wy-body-for-nav"> 
  <div class="wy-grid-for-nav">
    <nav data-toggle="wy-nav-shift" class="wy-nav-side">
      <div class="wy-side-scroll">
        <div class="wy-side-nav-search"  style="background: #343131" >
            <a href="../index.html" class="icon icon-home"> SIMULATeQCD
          </a>
<div role="search">
  <form id="rtd-search-form" class="wy-form" action="../search.html" method="get">
    <input type="text" name="q" placeholder="Search docs" />
    <input type="hidden" name="check_keywords" value="yes" />
    <input type="hidden" name="area" value="default" />
  </form>
</div>
        </div><div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="Navigation menu">
              <ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../01_gettingStarted/gettingStarted.html">Getting started</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="contributions.html">Contributions</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="codeStyle.html">Our coding style</a></li>
<li class="toctree-l2"><a class="reference internal" href="git.html">How to do pull requests</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeStructure.html">General structure of the code</a></li>
<li class="toctree-l2"><a class="reference internal" href="templates.html">Template instantiation</a></li>
<li class="toctree-l2"><a class="reference internal" href="terminalIO.html">Terminal output &amp; terminating the program</a></li>
<li class="toctree-l2"><a class="reference internal" href="timer.html">Timing your code</a></li>
<li class="toctree-l2"><a class="reference internal" href="inputParameter.html">How to make an input parameter file</a></li>
<li class="toctree-l2 current"><a class="current reference internal" href="#">Memory Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="multiGPU.html">Multi-GPU: Distribution of local lattices on the individual GPUs</a></li>
<li class="toctree-l2"><a class="reference internal" href="testing.html">Testing the code</a></li>
<li class="toctree-l2"><a class="reference internal" href="documenting.html">Documenting your code</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../03_applications/applications.html">Applications</a></li>
<li class="toctree-l1"><a class="reference internal" href="../04_codeBase/codeBase.html">Code base</a></li>
<li class="toctree-l1"><a class="reference internal" href="../05_modules/modules.html">Modules</a></li>
</ul>

        </div>
      </div>
    </nav>

    <section data-toggle="wy-nav-shift" class="wy-nav-content-wrap"><nav class="wy-nav-top" aria-label="Mobile navigation menu"  style="background: #343131" >
          <i data-toggle="wy-nav-top" class="fa fa-bars"></i>
          <a href="../index.html">SIMULATeQCD</a>
      </nav>

      <div class="wy-nav-content">
        <div class="rst-content">
          <div role="navigation" aria-label="Page navigation">
  <ul class="wy-breadcrumbs">
      <li><a href="../index.html" class="icon icon-home"></a> &raquo;</li>
          <li><a href="contributions.html">Contributions</a> &raquo;</li>
      <li>Memory Management</li>
      <li class="wy-breadcrumbs-aside">
            <a href="../_sources/02_contributions/memoryAllocation.md.txt" rel="nofollow"> View page source</a>
      </li>
  </ul>
  <hr/>
</div>
          <div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
           <div itemprop="articleBody">
             
  <section class="tex2jax_ignore mathjax_ignore" id="memory-management">
<h1>Memory Management<a class="headerlink" href="#memory-management" title="Permalink to this headline"></a></h1>
<div class="toggle admonition">
<p class="admonition-title">TL;DR:</p>
<p>The only functions you need to call from the outside to handle dynamic memory are:</p>
<div class="highlight-C++ notranslate"><div class="highlight"><pre><span></span><span class="c1">//! Obtain gMemoryPtr to dynamic memory based on the name:</span>
<span class="k">template</span><span class="o">&lt;</span><span class="kt">bool</span><span class="w"> </span><span class="n">onDevice</span><span class="o">&gt;</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">gMemoryPtr</span><span class="o">&lt;</span><span class="n">onDevice</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MemoryManagement</span><span class="o">::</span><span class="n">getMemAt</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">name</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">size</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span><span class="w"></span>

<span class="c1">//! Print a summary of the current state of the dynamic memory:</span>
<span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">MemoryManagement::memorySummary</span><span class="p">();</span><span class="w"></span>

<span class="c1">//! Retrieve or modify the content of the dynamic memory allocation:</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">floatT</span><span class="o">&gt;</span><span class="w"> </span><span class="n">__device__</span><span class="w">  </span><span class="n">__host__</span><span class="w"> </span><span class="kr">inline</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">MemoryAccessor</span><span class="o">::</span><span class="n">setValue</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">isite</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">floatT</span><span class="w"> </span><span class="n">value</span><span class="p">);</span><span class="w"></span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">floatT</span><span class="o">&gt;</span><span class="w"> </span><span class="n">__device__</span><span class="w">  </span><span class="n">__host__</span><span class="w"> </span><span class="kr">inline</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">MemoryAccessor</span><span class="o">::</span><span class="n">getValue</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">isite</span><span class="p">,</span><span class="w"> </span><span class="n">floatT</span><span class="w"> </span><span class="o">&amp;</span><span class="n">value</span><span class="p">)</span><span class="w"></span>

<span class="c1">//! Manipulate the gMemory object itself via gMemoryPtr-&gt;... :</span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">MemoryManagement</span><span class="o">::</span><span class="n">gMemory</span><span class="o">::</span><span class="n">adjustSize</span><span class="p">(</span><span class="kt">size_t</span><span class="w"> </span><span class="n">size</span><span class="p">)</span><span class="w"></span>
<span class="kt">void</span><span class="w"> </span><span class="n">MemoryManagement</span><span class="o">::</span><span class="n">gMemory</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">gMemoryPtr</span><span class="o">&lt;</span><span class="n">onDevice</span><span class="o">&gt;</span><span class="w"> </span><span class="o">&amp;</span><span class="n">src</span><span class="p">);</span><span class="w"></span>
<span class="kt">void</span><span class="w"> </span><span class="nf">MemoryManagement::gMemory::memset</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">value</span><span class="p">);</span><span class="w"></span>
<span class="k">template</span><span class="o">&lt;</span><span class="kt">bool</span><span class="w"> </span><span class="n">onDeviceSrc</span><span class="o">&gt;</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">MemoryManagement</span><span class="o">::</span><span class="n">gMemory</span><span class="o">::</span><span class="n">copyFrom</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">gMemoryPtr</span><span class="o">&lt;</span><span class="n">onDeviceSrc</span><span class="o">&gt;</span><span class="w"> </span><span class="o">&amp;</span><span class="n">src</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">sizeInBytes</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">offsetSelf</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="kt">size_t</span><span class="w"> </span><span class="n">offsetSrc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span><span class="w"></span>
<span class="kt">bool</span><span class="w"> </span><span class="nf">MemoryManagement::gMemory::adjustSize</span><span class="p">(</span><span class="kt">size_t</span><span class="w"> </span><span class="n">sizeBytes</span><span class="p">);</span><span class="w"></span>
<span class="kt">size_t</span><span class="w"> </span><span class="nf">MemoryManagement::gMemory::getSize</span><span class="p">()</span><span class="w"> </span><span class="k">const</span><span class="p">;</span><span class="w"></span>
<span class="p">...</span><span class="w"></span>
</pre></div>
</div>
</div>
<section id="motivation-for-making-our-own-pointer-class">
<h2>Motivation for making our own pointer class<a class="headerlink" href="#motivation-for-making-our-own-pointer-class" title="Permalink to this headline"></a></h2>
<p>The memory demands for lattice calculations can increase with increasing lattice size
in a nontrivial way, depending on the algorithm being used.
To help avoid surpassing hardware limitations, we would like a way to conveniently keep
track of all dynamically allocated memory at any given time. Additionally to avoid memory
leaks, dynamically allocated memory should be automatically deallocated when appropriate.
Since our code uses GPUs, one needs that memory allocation and deallocation are handled
through the appropriate API depending on the hardware.
Finally, dynamic memory allocation and deallocation can take a non-negligible amount of time,
so one can gain a performance boost by allowing a large chunk of temporary to be shared
between multiple objects.</p>
</section>
<section id="how-it-works">
<h2>How it works<a class="headerlink" href="#how-it-works" title="Permalink to this headline"></a></h2>
<p>The idea of the <code class="docutils literal notranslate"><span class="pre">MemoryManagement</span></code> class is to have a central object that manipulates and knows about all dynamic memory allocated in the code.
The <code class="docutils literal notranslate"><span class="pre">MemoryManagement</span></code> is never explicitly instantiated. We allow only certain methods
of this class to be callable by the user by making them static.
It works as follows: Each instance of dynamic memory is enclosed by a <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> object and referenced to the user through one or more corresponding <code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code> objects.
The content of the dynamic memory can only be accessed through the <code class="docutils literal notranslate"><span class="pre">MemoryAccessor</span></code> static class, and the memory object
itself can be manipulated through its public member functions which can be accessed by dereferencing the corresponding <code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code>’s.</p>
<p>A <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> object contains the raw pointer and the size in bytes of the allocated memory, as well as wrappers for GPU functions
needed to allocate memory on GPUs, and functions for copying, swapping, and resizing. From the outside you only interact with these
objects via <code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code>’s. The <code class="docutils literal notranslate"><span class="pre">MemoryManagement</span></code> class is the only thing in the code allowed to create <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> objects directly,
and <em>we should strive not to use any other kind of dynamically allocated memory when we code</em>. If we allocate our own dynamic memory
independent of the <code class="docutils literal notranslate"><span class="pre">MemoryManagement</span></code>, then it does not know about it, which defeats part of the purpose.</p>
<p>Within the <code class="docutils literal notranslate"><span class="pre">MemoryManagement</span></code>, <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> objects are stored in containers, which are implemented through <code class="docutils literal notranslate"><span class="pre">std::map</span></code>. Using <code class="docutils literal notranslate"><span class="pre">std::map</span></code>
we associate to each <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> object a  <code class="docutils literal notranslate"><span class="pre">name</span></code> (<code class="docutils literal notranslate"><span class="pre">std::string</span></code>). (For those of you familiar with python, we essentially have a dictionary
where the keys are the names and the values are the <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> objects.) There are separate containers for the device and host.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">MemoryManagement</span></code> enforces that if <code class="docutils literal notranslate"><span class="pre">getMemAt(name)</span></code> is called a second time with the same <code class="docutils literal notranslate"><span class="pre">name</span></code>, that the returned <code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code>
will point to its own <code class="docutils literal notranslate"><span class="pre">gMemory</span></code>, separate from the first time <code class="docutils literal notranslate"><span class="pre">getMemAt(name)</span></code> was called. (Hence we call this a <code class="docutils literal notranslate"><span class="pre">SmartName</span></code>.)
Internally the name is appended with
a unique “tag” (just a number starting at zero). For some very basic examples how this works, please read through <code class="docutils literal notranslate"><span class="pre">main_memManTest.cpp</span></code>
in the <code class="docutils literal notranslate"><span class="pre">src/testing</span></code> folder and compile+run it to see the output of <code class="docutils literal notranslate"><span class="pre">MemoryManagement::memorySummary()</span></code>.
If the name begins with “<code class="docutils literal notranslate"><span class="pre">SHARED_</span></code>” it will not append a tag and refer to the same memory every time you call <code class="docutils literal notranslate"><span class="pre">getMemAt</span></code>.
It will then only change the dynamic memory allocation when the size needs to be increased. Many dynamic memory allocations
of the code base are shared by default (for example halo buffers and lattice containers).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code> objects let you interact with the <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> of a specific name and can be used just like real pointers.
<code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code> objects are special in that they comply with all this name/container functionality. Again, you will never interact
with a <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> object directly in your code; instead you will interact with (one of) its associated <code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code>.
The <code class="docutils literal notranslate"><span class="pre">MemoryManagement</span></code> keeps track of how many <code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code> to any given <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> are alive. Once every <code class="docutils literal notranslate"><span class="pre">gMemoryPtr</span></code> that
points to a specific <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> object is destroyed, the <code class="docutils literal notranslate"><span class="pre">gMemory</span></code> itself will be destroyed and the dynamic memory freed.
In this way we don’t need to keep track of the dynamic memory ourselves, and no memory leaks should occur.</p>
<p>Here is an example of how you can allocate and manipulate dynamic memory on GPUs:</p>
<div class="highlight-C++ notranslate"><div class="highlight"><pre><span></span><span class="c1">/// Allocate some memory; call its pointer mem_1, and label it DescriptiveName</span>
<span class="n">gMemoryPtr</span><span class="o">&lt;</span><span class="nb">true</span><span class="o">&gt;</span><span class="w"> </span><span class="n">mem_1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MemoryManagement</span><span class="o">::</span><span class="n">getMemAt</span><span class="o">&lt;</span><span class="nb">true</span><span class="o">&gt;</span><span class="p">(</span><span class="s">&quot;DescriptiveName&quot;</span><span class="p">);</span><span class="w"></span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">mem_1</span><span class="o">-&gt;</span><span class="n">getSize</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span><span class="w"></span>

<span class="c1">/// Change the size of the memory to which it points to 2024 bytes.</span>
<span class="n">mem_1</span><span class="o">-&gt;</span><span class="n">adjustSize</span><span class="p">(</span><span class="mi">2024</span><span class="p">);</span><span class="w"> </span><span class="c1">//! This calls a public method of the gMemory object</span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">mem_1</span><span class="o">-&gt;</span><span class="n">getSize</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span><span class="w"></span>

<span class="c1">/// Copy construct another gMemoryPtr:</span>
<span class="n">gMemoryPtr</span><span class="o">&lt;</span><span class="nb">true</span><span class="o">&gt;</span><span class="w"> </span><span class="n">mem_2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mem_1</span><span class="p">;</span><span class="w"></span>
<span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">mem_2</span><span class="o">-&gt;</span><span class="n">getSize</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span><span class="w"></span>
</pre></div>
</div>
<p>The output will be as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">0</span>
<span class="mi">2024</span>
<span class="mi">2024</span>
</pre></div>
</div>
</section>
</section>


           </div>
          </div>
          <footer>

  <hr/>

  <div role="contentinfo">
    <p>&#169; Copyright 2021, LatticeQCD.</p>
  </div>

  Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
    <a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
    provided by <a href="https://readthedocs.org">Read the Docs</a>.
   

</footer>
        </div>
      </div>
    </section>
  </div>
  <script>
      jQuery(function () {
          SphinxRtdTheme.Navigation.enable(true);
      });
  </script> 

</body>
</html>